
package com.idealighter.game.games.xzdd.struct;

import com.idealighter.game.games.common.AbstractTable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 麻将桌子 .
 * 
 * @date 2016年8月23日 上午10:25:35
 *
 */
public class XzddTable extends AbstractTable {

  // 座位数量
  public static final int SEAT_NUM = 4;

  public final XzddRoom room;
  public final List<XzddSeat> seats;
  // 本桌麻将
  public final List<XzddMj> mjs;
  // 本桌麻将当前摸牌index(即将要摸的那张),从0计数
  public int drawIndex = 0;
  // 本桌玩家换牌的麻将
  public final List<Integer> exchangeMjs = new ArrayList<>();
  // 骰子点数1
  public int dice1 = 0;
  // 骰子点数2
  public int dice2 = 0;
  // 庄家
  public XzddSeat dealer = null;
  // 游戏阶段
  public XzddStage stage = XzddStage.READY;
  // 上一次玩家出的麻将
  public int prePlayMj = 0;
  // 上一次出牌的玩家id
  public long prePlayer = 0;
  // 上一次杠牌成功的玩家
  public XzddSeat preGangedSeat = null;
  // 上一次面下杠的麻将(但是未杠成功的牌，主要被抢杠胡使用)
  public int preMianXiaGangMj = 0;
  // 上一次面下杠的玩家
  public long preMianXiaGangPlayer = 0;
  // 下一个应该出牌的玩家
  public XzddSeat nextPlaySeat = null;
  // 玩家结算信息
  public final Map<Long, XzddPlayerBill> playerBills = new HashMap<>();

  /**
   * 构造函数 .
   * 
   * @param id .
   * @param room .
   */
  public XzddTable(int id, XzddRoom room) {
    super(id);
    this.room = room;
    this.seats = createSeats();
    this.mjs = createMjs();
  }

  /**
   * 重置桌子数据 .
   */
  public void reset() {
    this.drawIndex = 0;
    this.exchangeMjs.clear();
    this.dice1 = 0;
    this.dice2 = 0;
    this.dealer = null;
    this.stage = XzddStage.READY;
    this.prePlayMj = 0;
    this.prePlayer = 0;
    this.preGangedSeat = null;
    this.preMianXiaGangMj = 0;
    this.preMianXiaGangPlayer = 0;
    this.nextPlaySeat = null;
    this.playerBills.clear();
  }

  /**
   * 重置seats抢牌状态 .
   */
  public void resetSeatsGrabState() {
    // 抢牌结束后重置抢牌状态
    for (XzddSeat s : seats) {
      s.resetGrabState();
    }
  }

  /**
   * 创建位置.
   * 
   * @return
   */
  private List<XzddSeat> createSeats() {
    List<XzddSeat> seats = new ArrayList<>(SEAT_NUM);
    for (int i = 0; i < SEAT_NUM; i++) {
      seats.add(new XzddSeat(i, this));
    }

    return Collections.unmodifiableList(seats);
  }

  /**
   * 创建麻将 .
   * 
   * @return
   */
  private List<XzddMj> createMjs() {
    List<XzddMj> mjs = new ArrayList<>();
    Collections.addAll(mjs, XzddMj.values());
    Collections.addAll(mjs, XzddMj.values());
    Collections.addAll(mjs, XzddMj.values());
    Collections.addAll(mjs, XzddMj.values());
    return mjs;
  }

  /**
   * 获取座位 .
   * 
   * @param order .
   * @return
   */
  public XzddSeat getSeat(int order) {
    return seats.get(order);
  }

  /**
   * 是否还有麻将 .
   * 
   * @return
   */
  public boolean hasMj() {
    return drawIndex < mjs.size();
  }

  /**
   * 抢牌是否有人正 .
   * 
   * @param excludeSeat . 除去的seat，其他seat是否正在胡，null不排除
   * @return
   */
  public boolean huIng(XzddSeat excludeSeat) {
    for (XzddSeat s : seats) {
      if (s != excludeSeat && s.huState == XzddGrabState.GRABING) {
        return true;
      }
    }

    return false;
  }

  /**
   * 抢牌是否有人胡过 .
   * 
   * @param excludeSeat . 除去的seat，其他seat是否胡过，null不排除
   * @return
   */
  public boolean hued(XzddSeat excludeSeat) {
    for (XzddSeat s : seats) {
      if (s != excludeSeat && s.huState == XzddGrabState.GRABED) {
        return true;
      }
    }

    return false;
  }

  /**
   * 抢牌杠过的seat,但是还未成功 .
   * 
   * @return
   */
  public XzddSeat gangedSeat() {
    for (XzddSeat s : seats) {
      if (s.gangState == XzddGrabState.GRABED) {
        return s;
      }
    }

    return null;
  }

  /**
   * 抢牌是否结束 .
   * 
   * @return
   */
  public boolean grabOver() {
    for (XzddSeat s : seats) {
      if (s.pengState == XzddGrabState.GRABING || s.gangState == XzddGrabState.GRABING
          || s.huState == XzddGrabState.GRABING) {
        return false;
      }
    }

    return true;
  }

  /**
   * 未结束的座位数量 .
   * 
   * @return
   */
  public int notOverSeatsNum() {
    int notOverNum = 0;
    for (XzddSeat s : seats) {
      if (s.getPlayerId() > 0 && !s.over) {
        notOverNum++;
      }
    }

    return notOverNum;
  }

  /**
   * 游戏是否结束,没有麻将可摸或只剩一个人未结束 .
   * 
   * @return
   */
  public boolean gameOver() {
    if (hasMj()) {
      return notOverSeatsNum() < 2;
    }

    return true;
  }

  /**
   * 桌子是否准备好.
   * 
   * @return
   */
  public boolean readyOver() {
    for (XzddSeat s : seats) {
      if (!s.readied()) {
        return false;
      }
    }

    return true;
  }

  /**
   * 桌子是否定缺好 .
   * 
   * @return
   */
  public boolean missingOver() {
    for (XzddSeat s : seats) {
      if (s.getPlayerId() > 0 && s.cards.missing == null) {
        return false;
      }
    }

    return true;
  }

  /**
   * 换牌成功 .
   * 
   * @return
   */
  public boolean exchangeOver() {
    for (XzddSeat s : seats) {
      if (s.getPlayerId() > 0 && s.exchangeNum < 0) {
        return false;
      }
    }

    return true;
  }

  /**
   * 计算下一个出牌order .
   * 
   * @return
   */
  public XzddSeat nextPlaySeat(XzddSeat seat) {
    int startOrder = seat.getOrder();
    for (int i = 1; i < SEAT_NUM; i++) {
      XzddSeat newNextPlaySeat = seats.get((startOrder + i) % SEAT_NUM);
      if (newNextPlaySeat.getPlayerId() > 0 && !newNextPlaySeat.over) {
        return newNextPlaySeat;
      }
    }

    return null;
  }

  @SuppressWarnings("unchecked")
  @Override
  public XzddRoom room() {
    return room;
  }

  @Override
  public List<XzddSeat> seats() {
    return seats;
  }

}
